home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / PowerLisp 1.1 / Library / assembler.lisp < prev    next >
Encoding:
Text File  |  1994-03-25  |  25.1 KB  |  863 lines  |  [TEXT/ROSA]

  1. ;;;
  2. ;;;        Copyright © 1994 Roger Corman.  All rights reserved.
  3. ;;;
  4.  
  5. ;
  6. ;    Source code for assembler.
  7. ;
  8.  
  9. ;
  10. ;    We do an eval-when on the entire file so that we get the
  11. ;    performance benefits immediately
  12. ;
  13. (eval-when (:compile-toplevel :load-toplevel :execute)
  14.     (provide :assembler)
  15.     (in-package :assembler))
  16.  
  17. (eval-when (:compile-toplevel :load-toplevel :execute)
  18. (export 
  19. '(
  20.      a0  a1  a2  a3  a4  a5  a6  a7
  21.     -a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7
  22.      a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+
  23.      d0  d1  d2  d3  d4  d5  d6  d7
  24.     d-registers
  25.     a-registers
  26.     a-inc-registers
  27.     a-dec-registers
  28.     $CAR
  29.     $CDR
  30.     $SETCAR
  31.     $SETCDR
  32.     $SYMBOL-VALUE
  33.     $SYMBOL-PLIST
  34.     $NODE-TYPE
  35.     $CONSP
  36.     $INTEGER
  37.     $RETURN
  38.     $FUNC-BEGIN
  39.     $IF
  40.     $IFELSE
  41.     $REFERENCE
  42.     link
  43.     unlk
  44.     rts
  45.     dc.w
  46.     dc.l
  47.     moveq
  48.     move.l
  49.     move.b
  50.     move.w
  51.     movea.l
  52.     add.l
  53.     addi.l
  54.     and.l
  55.     andi.l
  56.     or.l
  57.     ori.l
  58.     eor.l
  59.     eori.l
  60.     sub.l
  61.     cmp.l
  62.     tst.l
  63.     subi.l
  64.     clr.l
  65.     lea
  66.     jsr
  67.     bra
  68.     bsr
  69.     bhi
  70.     bls
  71.     bcc
  72.     bcs
  73.     bne
  74.     beq
  75.     bvc
  76.     bvs
  77.     bpl
  78.     bmi
  79.     bge
  80.     blt
  81.     bgt
  82.     ble
  83.     movem.l
  84. )))
  85.  
  86. (defconstant a0 0)
  87. (defconstant a1 1)
  88. (defconstant a2 2)
  89. (defconstant a3 3)
  90. (defconstant a4 4)
  91. (defconstant a5 5)
  92. (defconstant a6 6)
  93. (defconstant a7 7)
  94.  
  95. (defconstant a0+ 0)
  96. (defconstant a1+ 1)
  97. (defconstant a2+ 2)
  98. (defconstant a3+ 3)
  99. (defconstant a4+ 4)
  100. (defconstant a5+ 5)
  101. (defconstant a6+ 6)
  102. (defconstant a7+ 7)
  103.  
  104. (defconstant -a0 0)
  105. (defconstant -a1 1)
  106. (defconstant -a2 2)
  107. (defconstant -a3 3)
  108. (defconstant -a4 4)
  109. (defconstant -a5 5)
  110. (defconstant -a6 6)
  111. (defconstant -a7 7)
  112.  
  113. (defconstant d0 0)
  114. (defconstant d1 1)
  115. (defconstant d2 2)
  116. (defconstant d3 3)
  117. (defconstant d4 4)
  118. (defconstant d5 5)
  119. (defconstant d6 6)
  120. (defconstant d7 7)
  121.  
  122. (defconstant d-registers '(d0 d1 d2 d3 d4 d5 d6 d7))
  123. (defconstant a-registers '(a0 a1 a2 a3 a4 a5 a6 a7))
  124. (defconstant a-inc-registers '(a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+))
  125. (defconstant a-dec-registers '(-a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7))
  126.  
  127. ;;    Macros to access SYMBOL and NODE fields.
  128. ;;    These are dependent on the symbol class definition.
  129. ;;    The C++ source is in LispObjects.h.
  130.  
  131. (defconstant *symbol-value-offset*                 8)
  132. (defconstant *symbol-plist-offset*                 12)
  133. (defconstant *symbol-package-offset*             16)
  134. (defconstant *symbol-name-offset*                 20)
  135. (defconstant *symbol-flags-offset*                 24)
  136. (defconstant *symbol-jump-table-entry-offset*     26)
  137. (defconstant *symbol-jump-address-offset*         28)
  138. (defconstant *symbol-function-offset*             32)
  139.  
  140. (defconstant *node-car-offset*                    0)
  141. (defconstant *node-cdr-offset*                    4)
  142. (defconstant *node-flags-offset*                8)
  143. (defconstant *node-type-offset*                    9)
  144.  
  145. (defconstant *node-integer-offset*                0)    ;; occupies the car field
  146.  
  147. (defvar *assembler-address*    0)
  148. (defvar *assembler-local-address*    0)    ;; keep track of offset within instruction
  149. (defvar *assembler-references*    nil)
  150.  
  151. ;
  152. ;    We do an eval-when on the entire file so that we get the
  153. ;    performance benefits immediately
  154. ;
  155. (eval-when (:compile-toplevel :load-toplevel :execute)
  156.  
  157. (defmacro $CAR (areg &optional dest-reg)
  158.     (unless dest-reg (setq dest-reg areg))
  159.     `(
  160.         (move.l (,areg ,*node-car-offset*) ,dest-reg)
  161.      )) 
  162.  
  163. (defmacro $CDR (areg &optional dest-reg)
  164.     (unless dest-reg (setq dest-reg areg))
  165.     `(
  166.         (move.l (,areg ,*node-cdr-offset*) ,dest-reg)
  167.      )) 
  168.  
  169. (defmacro $SETCAR (areg value)
  170.     `(
  171.         (move.l ,value (,areg ,*node-car-offset*))
  172.      )) 
  173.  
  174. (defmacro $SETCDR (areg value)
  175.     `(
  176.         (move.l ,value (,areg ,*node-cdr-offset*))
  177.      )) 
  178.  
  179. (defmacro $SYMBOL-VALUE (areg)
  180.     `(
  181.         (move.l (,areg) ,areg)
  182.         (move.l (,areg ,*symbol-value-offset*) ,areg)
  183.         (move.l (,areg) ,areg)
  184.      )) 
  185.  
  186. (defmacro $SYMBOL-PLIST (areg)
  187.     `(
  188.         (move.l (,areg) ,areg)
  189.         (move.l (,areg ,*symbol-plist-offset*) ,areg)
  190.      )) 
  191.  
  192. ;; Extract the type field from a node
  193. (defmacro $NODE-TYPE (areg dest)
  194.     `(
  195.         (move.l (,areg ,(- *node-type-offset* 3)) ,dest)
  196.         (andi.l #x000000ff ,dest)
  197.     ))
  198.     
  199. (defmacro $CONSP (areg)
  200.     `(
  201.         ($NODE-TYPE ,areg d0)
  202.         (cmp.l 0 d0)
  203.     ))
  204.  
  205. (defmacro $INTEGER (areg &optional dest-reg)
  206.     (unless dest-reg (setq dest-reg areg))
  207.     `(
  208.         (move.l (,areg ,*node-integer-offset*) ,dest-reg)
  209.      )) 
  210.  
  211.     
  212. ;;
  213. ;;    The $RETURN macro zeros out the multiple value cell, stores
  214. ;;    the passed value in d0 (to return it), and unlinks the stack frame.
  215. ;;
  216. (defmacro $RETURN (retval)
  217.     (if (eq retval 'd0)
  218.         `(
  219.             (clr.l (common-lisp::%multiple-values-address))
  220.             (unlk a6)
  221.             (rts)
  222.          ) 
  223.         `(
  224.             (clr.l (common-lisp::%multiple-values-address))
  225.             (move.l ,retval d0)
  226.             (unlk a6)
  227.             (rts)
  228.          ))) 
  229.  
  230. ;;
  231. ;;    The $FUNC-BEGIN macro sets up the A6 stack frame link,
  232. ;;    and stores a pointer to the parameter block in A0.
  233. ;;    Usage:
  234. ;;        ($FUNC-BEGIN 4)        ;; allocates 4 bytes (space for one object)
  235. ;;                            ;; on the stack
  236. ;;
  237. (defmacro $FUNC-BEGIN (size)
  238.     `(
  239.         (link a6 ,size)
  240.         (move.l (a6 8) a0)
  241.      )) 
  242.  
  243. ;;
  244. ;;    $IF macro
  245. ;;    Usage:
  246. ;;        ($IF    
  247. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next statement will be executed
  248. ;;            (
  249. ;;                (move.l d0 d3)
  250. ;;            ))
  251. ;;
  252. (defmacro $IF (condition instructions)
  253.     (let ((temp-label (gensym)))
  254.         ;;    allow single instruction clauses or lists of instructions
  255.         (if (not (listp (car condition)))
  256.             (setq condition (list condition)))
  257.         (if (not (listp (car instructions)))
  258.             (setq instructions (list instructions)))
  259.  
  260.         `(
  261.             ,@condition
  262.             (bne ,temp-label)
  263.             ,@instructions
  264.             ,temp-label
  265.          ))) 
  266.  
  267. ;;
  268. ;;    $IFELSE macro
  269. ;;    Usage:
  270. ;;        ($IFELSE    
  271. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next instruction will be executed
  272. ;;            (
  273. ;;                (move.l d0 d3)
  274. ;;            )
  275. ;;            (
  276. ;;                (move.l d2 d3)    ;; otherwise this instruction will be executed
  277. ;;            ))
  278. ;;
  279. (defmacro $IFELSE (condition if-instructions else-instructions)
  280.     (let ((else-label (gensym)) 
  281.           (exit-label (gensym)))
  282.  
  283.         ;;    allow single instruction clauses or lists of instructions
  284.         (if (not (listp (car condition)))
  285.             (setq condition (list condition)))
  286.         (if (not (listp (car if-instructions)))
  287.             (setq if-instructions (list if-instructions)))
  288.         (if (not (listp (car else-instructions)))
  289.             (setq else-instructions (list else-instructions)))
  290.         
  291.         `(
  292.             ,@condition
  293.             (bne ,else-label)
  294.             ,@if-instructions
  295.             (bra ,exit-label)
  296.             ,else-label
  297.             ,@else-instructions
  298.             ,exit-label
  299.          ))) 
  300.  
  301. ;;
  302. ;;    The $REFERENCE macro does not generate any instructions, but
  303. ;;    is used by the compiler as a flag to the assembler to correctly
  304. ;;    generate address reference entries when code is compiled to a file.
  305. ;;
  306. (defmacro $REFERENCE (referenced-item)
  307.     nil)
  308.     
  309. (defmacro link (areg offset) `(,(+ (symbol-value areg) #x4e50) ,offset))
  310. (defmacro unlk (areg) `(,(+ (symbol-value areg) #x4e58)))
  311. (defmacro rts () `(#x4e75))
  312. (defmacro dc.w (w) 
  313.     (cond 
  314.         ((symbolp w) 
  315.          (add-reference `(%symbol-value-word ,w) -2)
  316.          (list (symbol-value w)))
  317.         (t (list w))))
  318.  
  319. (defmacro dc.l (w) 
  320.     (cond 
  321.         ((symbolp w) 
  322.          (add-reference `(%symbol-value ,w) -2)
  323.          (multiple-value-list (truncate (symbol-value w) #x10000)))
  324.         (t (multiple-value-list (truncate w #x10000)))))
  325.         
  326. (defmacro moveq (byte dreg)
  327.     (if (or (< byte 0) (> byte 255)) 
  328.         (error "Data out of range.~%Instruction: moveq  Value: ~A" byte))
  329.     (unless (member dreg d-registers) 
  330.         (error "Invalid data register. ~%Instruction: moveq  Operand: ~A" dreg))
  331.     (list (+ #x7000 byte (* (symbol-value dreg) #x200))))
  332.  
  333. (defmacro move.l (sreg dreg)
  334.     (move-instruction sreg dreg 'long))
  335.  
  336. (defmacro move.b (sreg dreg)
  337.     (move-instruction sreg dreg 'byte))
  338.  
  339. (defmacro move.w (sreg dreg)
  340.     (move-instruction sreg dreg 'word))
  341.  
  342. (defun move-instruction (sreg dreg size)
  343.     (let ((s (encode-address sreg size))(d (encode-address dreg size)) op-code)
  344.         (setq op-code 
  345.             (case size
  346.                 (long #x2000)
  347.                 (byte #x1000)
  348.                 (word #x3000)))
  349.         `(,(+ op-code 
  350.                 (* (encoded-address-reg d) #x200) ; destination register bits 9-11
  351.                 (* (encoded-address-mode d) #x40) ; destination mode bits 6-8
  352.                 (* (encoded-address-mode s) #x8)  ; source mode bits 3-5
  353.                 (encoded-address-reg s))          ; source register
  354.             ,@(encoded-address-data s)
  355.             ,@(encoded-address-data d))))
  356.         
  357.             
  358. (defmacro movea.l (sreg dreg)
  359.     (unless (member dreg a-registers) 
  360.         (error "Invalid address register. ~%Instruction: movea.l  Operand: ~A" dreg))
  361.     (let ((s (encode-address sreg))(d (symbol-value dreg)))
  362.         (append
  363.             (list (+ #x2040 
  364.                     (* d #x200)                ; destination register bits 9-11
  365.                     (* (encoded-address-mode s) #x8) ; source mode bits 3-5
  366.                     (encoded-address-reg s)))         ; source register
  367.             (encoded-address-data s))))
  368.  
  369. (defmacro add.l (src dest)
  370.     (let ((s (encode-address src))(d (encode-address dest)))
  371.         (unless (or (= (encoded-address-mode s) 0) 
  372.                     (= (encoded-address-mode d) 0))
  373.             (error 
  374.                 "The source or destination must be a d-register. ~%Instruction: add.l  Operands: ~A, ~A" src dest))
  375.         (if (= (encoded-address-mode s) 0)    ; if D-register is source
  376.             `(,(+ #xD000 
  377.                 (* (encoded-address-reg s) #x200)        ; source register bits 9-11
  378.                 (* 6 #x40)                                ; op-mode bits 6-8
  379.                 (* (encoded-address-mode d) #x8)        ; dest mode bits 3-5
  380.                 (encoded-address-reg d))                ; dest register
  381.                 ,@(encoded-address-data d))
  382.                                         ; else D-register is destination
  383.             `(,(+ #xD000 
  384.                 (* (encoded-address-reg d) #x200)        ; dest register bits 9-11
  385.                 (* 2 #x40)                                ; op-mode bits 6-8
  386.                 (* (encoded-address-mode s) #x8)        ; src mode bits 3-5
  387.                 (encoded-address-reg s))                ; src register
  388.                 ,@(encoded-address-data s)))))
  389.  
  390. (defmacro addi.l (src dest)
  391.     (incf *assembler-local-address* 4)
  392.     (let ((s src)(d (encode-address dest)))
  393.         (unless (integerp s)
  394.             (error "The source must be an integer. ~%Instruction: addi.l  Operand: ~A" s))
  395.         `(,(+ #x0680 
  396.                 (* (encoded-address-mode d) #x8)    ; dest mode bits 3-5
  397.                 (encoded-address-reg d))            ; dest register
  398.                 ,@(multiple-value-list (truncate s #x10000))
  399.                 ,@(encoded-address-data d))))
  400.  
  401. (defmacro and.l (src dest)
  402.     (let ((s (encode-address src))(d (encode-address dest)))
  403.         (unless (or (= (encoded-address-mode s) 0) 
  404.                     (= (encoded-address-mode d) 0))
  405.             (error 
  406.                 "The source or destination must be a d-register. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  407.         (if (or (= (encoded-address-mode s) 1) 
  408.                 (= (encoded-address-mode d) 1))
  409.             (error 
  410.                 "A-register not allowed as operand. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  411.         (if (= (encoded-address-mode s) 0); if D-register is source
  412.             `(,(+ #xC000 
  413.                 (* (encoded-address-reg s) #x200) ; source register bits 9-11
  414.                 (* 6 #x40)                        ; op-mode bits 6-8
  415.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  416.                 (encoded-address-reg d))        ; dest register
  417.                 ,@(encoded-address-data d))
  418.                                         ; else D-register is destination
  419.             `(,(+ #xC000 
  420.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  421.                 (* 2 #x40)                        ; op-mode bits 6-8
  422.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  423.                 (encoded-address-reg s))        ; src register
  424.                 ,@(encoded-address-data s)))))
  425.  
  426. (defmacro andi.l (src dest)
  427.     (incf *assembler-local-address* 4)
  428.     (let ((s src)(d (encode-address dest)))
  429.         (unless (integerp s)
  430.             (error "The source must be an integer. ~%Instruction: andi.l  Operand: ~A" src))
  431.         (if (= (encoded-address-mode d) 1)
  432.             (error "A-register not allowed as destination. ~%Instruction: andi.l  Operand: ~A" dest))
  433.         `(,(+ #x0280 
  434.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  435.                 (encoded-address-reg d))        ; dest register
  436.                 ,@(multiple-value-list (truncate s #x10000))
  437.                 ,@(encoded-address-data d))))
  438.  
  439. (defmacro or.l (src dest)
  440.     (let ((s (encode-address src))(d (encode-address dest)))
  441.         (unless (or (= (encoded-address-mode s) 0) 
  442.                     (= (encoded-address-mode d) 0))
  443.             (error 
  444.                 "The source or destination must be a d-register. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  445.         (if (or (= (encoded-address-mode s) 1) 
  446.                 (= (encoded-address-mode d) 1))
  447.             (error 
  448.                 "A-register not allowed as operand. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  449.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  450.             `(,(+ #x8000 
  451.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  452.                 (* 6 #x40)                        ; op-mode bits 6-8
  453.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  454.                 (encoded-address-reg d))        ; dest register
  455.                 ,@(encoded-address-data d))
  456.                                         ; else D-register is destination
  457.             `(,(+ #x8000 
  458.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  459.                 (* 2 #x40)                        ; op-mode bits 6-8
  460.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  461.                 (encoded-address-reg s))        ; src register
  462.                 ,@(encoded-address-data s)))))
  463.  
  464. (defmacro ori.l (src dest)
  465.     (incf *assembler-local-address* 4)
  466.     (let ((s src)(d (encode-address dest)))
  467.         (unless (integerp s)
  468.             (error "The source of 'ori' must be an integer"))
  469.         (if (= (encoded-address-mode d) 1)
  470.             (error "ori: destination cannot be an a-register"))
  471.         `(,(+ #x0080 
  472.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  473.                 (encoded-address-reg d))        ; dest register
  474.                 ,@(multiple-value-list (truncate s #x10000))
  475.                 ,@(encoded-address-data d))))
  476.  
  477. (defmacro eor.l (src dest)
  478.     (let ((s (encode-address src))(d (encode-address dest)))
  479.         (unless (= (encoded-address-mode s) 0)
  480.             (error "eor: source must be a d-register"))
  481.         (if (= (encoded-address-mode d) 1)
  482.             (error "eor: destination cannot be an a-register"))
  483.         `(,(+ #xB000 
  484.             (* (encoded-address-reg s) #x200); source register bits 9-11
  485.             (* 6 #x40)                        ; op-mode bits 6-8
  486.             (* (encoded-address-mode d) #x8); dest mode bits 3-5
  487.             (encoded-address-reg d))        ; dest register
  488.             ,@(encoded-address-data d))))
  489.  
  490. (defmacro eori.l (src dest)
  491.     (incf *assembler-local-address* 4)
  492.     (let ((s src)(d (encode-address dest)))
  493.         (unless (integerp s)
  494.             (error "The source of 'eori' must be an integer"))
  495.         (if (= (encoded-address-mode d) 1)
  496.             (error "eor.i: destination cannot be an a-register"))
  497.         `(,(+ #x0A80 
  498.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  499.                 (encoded-address-reg d))        ; dest register
  500.                 ,@(multiple-value-list (truncate s #x10000))
  501.                 ,@(encoded-address-data d))))
  502.  
  503. (defmacro sub.l (src dest)
  504.     (let ((s (encode-address src))(d (encode-address dest)))
  505.         (unless (or (= (encoded-address-mode s) 0) 
  506.                     (= (encoded-address-mode d) 0))
  507.             (error "The source or destination of 'sub' must be a d-register"))
  508.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  509.             `(,(+ #x9000 
  510.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  511.                 (* 6 #x40)                        ; op-mode bits 6-8
  512.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  513.                 (encoded-address-reg d))        ; dest register
  514.                 ,@(encoded-address-data d))
  515.                                         ; else D-register is destination
  516.             `(,(+ #x9000 
  517.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  518.                 (* 2 #x40)                        ; op-mode bits 6-8
  519.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  520.                 (encoded-address-reg s))        ; src register
  521.                 ,@(encoded-address-data s)))))
  522.  
  523. (defmacro cmp.l (src dest)
  524.     (let ((s (encode-address src))(d (encode-address dest)))
  525.         (unless (= (encoded-address-mode d) 0)
  526.             (error "The destination of 'cmp' must be a d-register"))
  527.         `(,(+ #xb000 
  528.             (* (encoded-address-reg d) #x200); dest register bits 9-11
  529.             (* 2 #x40)                        ; op-mode bits 6-8
  530.             (* (encoded-address-mode s) #x8); src mode bits 3-5
  531.             (encoded-address-reg s))        ; src register
  532.             ,@(encoded-address-data s))))
  533.  
  534. (defmacro tst.l (dest)
  535.     (let ((d (encode-address dest)))
  536.         `(,(+ #x4A00
  537.                 (* #x40 2)                        ; size = long
  538.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  539.                 (encoded-address-reg d))        ; dest register
  540.                 ,@(encoded-address-data d))))
  541.  
  542. (defmacro subi.l (src dest)
  543.     (incf *assembler-local-address* 4)
  544.     (let ((s src)(d (encode-address dest)))
  545.         (unless (integerp s)
  546.             (error "The source of 'subi' must be an integer"))
  547.         `(,(+ #x0480 
  548.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  549.                 (encoded-address-reg d))        ; dest register
  550.                 ,@(multiple-value-list (truncate s #x10000))
  551.                 ,@(encoded-address-data d))))
  552.  
  553. (defmacro clr.l (dest)
  554.     (let ((d (encode-address dest)))
  555.         `(,(+ #x4200
  556.                 (* #x40 2)                        ; size = long
  557.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  558.                 (encoded-address-reg d))        ; dest register
  559.                 ,@(encoded-address-data d))))
  560.  
  561. (defmacro lea (src dest)
  562.     (let ((s (encode-address src))(d (encode-address dest)))
  563.         (unless (= (encoded-address-mode d) 1)
  564.             (error "The destination of 'lea' must be an a-register"))
  565.         `(,(+ #x41C0
  566.                 (* #x200 (encoded-address-reg d)); dest register bits 9-11
  567.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  568.                 (encoded-address-reg s))        ; src register
  569.                 ,@(encoded-address-data s))))
  570.  
  571. (defmacro jsr (dst)
  572.  
  573.     (if (symbolp dst) 
  574.         (progn
  575.             (add-reference `(symbol-value ,dst))
  576.             (setq dst (symbol-value dst))))
  577.             
  578.     (if (consp dst)
  579.         (if (eq (car dst) 'function)
  580.             (progn
  581.                 (add-reference dst)
  582.                 (return (cons #x4eb9 
  583.                     (multiple-value-list 
  584.                         (truncate (exec-address (cadr dst)) #x10000))))))
  585.         ;; else
  586.         (error "Invalid destination.~%Instruction: jsr  Destination: ~A" dst))
  587.         
  588.     (let ((d (encode-address dst)))
  589.         (append
  590.             (list (+ #x4e80
  591.                     (* (encoded-address-mode d) #x8); dest mode bits 3-5
  592.                     (encoded-address-reg d)))        ; dest register
  593.             (encoded-address-data d))))
  594.  
  595. (defmacro bra (dest) `(#x6000 ,dest))
  596. (defmacro bsr (dest) `(#x6100 ,dest))
  597. (defmacro bhi (dest) `(#x6200 ,dest))
  598. (defmacro bls (dest) `(#x6300 ,dest))
  599. (defmacro bcc (dest) `(#x6400 ,dest))
  600. (defmacro bcs (dest) `(#x6500 ,dest))
  601. (defmacro bne (dest) `(#x6600 ,dest))
  602. (defmacro beq (dest) `(#x6700 ,dest))
  603. (defmacro bvc (dest) `(#x6800 ,dest))
  604. (defmacro bvs (dest) `(#x6900 ,dest))
  605. (defmacro bpl (dest) `(#x6a00 ,dest))
  606. (defmacro bmi (dest) `(#x6b00 ,dest))
  607. (defmacro bge (dest) `(#x6c00 ,dest))
  608. (defmacro blt (dest) `(#x6d00 ,dest))
  609. (defmacro bgt (dest) `(#x6e00 ,dest))
  610. (defmacro ble (dest) `(#x6f00 ,dest))
  611.     
  612. (setf (get 'd0 'post-increment-mask) #x0001)
  613. (setf (get 'd1 'post-increment-mask) #x0002)
  614. (setf (get 'd2 'post-increment-mask) #x0004)
  615. (setf (get 'd3 'post-increment-mask) #x0008)
  616. (setf (get 'd4 'post-increment-mask) #x0010)
  617. (setf (get 'd5 'post-increment-mask) #x0020)
  618. (setf (get 'd6 'post-increment-mask) #x0040)
  619. (setf (get 'd7 'post-increment-mask) #x0080)
  620. (setf (get 'a0 'post-increment-mask) #x0100)
  621. (setf (get 'a1 'post-increment-mask) #x0200)
  622. (setf (get 'a2 'post-increment-mask) #x0400)
  623. (setf (get 'a3 'post-increment-mask) #x0800)
  624. (setf (get 'a4 'post-increment-mask) #x1000)
  625. (setf (get 'a5 'post-increment-mask) #x2000)
  626. (setf (get 'a6 'post-increment-mask) #x4000)
  627. (setf (get 'a7 'post-increment-mask) #x8000)
  628.  
  629. (setf (get 'a7 'pre-decrement-mask) #x0001)
  630. (setf (get 'a6 'pre-decrement-mask) #x0002)
  631. (setf (get 'a5 'pre-decrement-mask) #x0004)
  632. (setf (get 'a4 'pre-decrement-mask) #x0008)
  633. (setf (get 'a3 'pre-decrement-mask) #x0010)
  634. (setf (get 'a2 'pre-decrement-mask) #x0020)
  635. (setf (get 'a1 'pre-decrement-mask) #x0040)
  636. (setf (get 'a0 'pre-decrement-mask) #x0080)
  637. (setf (get 'd7 'pre-decrement-mask) #x0100)
  638. (setf (get 'd6 'pre-decrement-mask) #x0200)
  639. (setf (get 'd5 'pre-decrement-mask) #x0400)
  640. (setf (get 'd4 'pre-decrement-mask) #x0800)
  641. (setf (get 'd3 'pre-decrement-mask) #x1000)
  642. (setf (get 'd2 'pre-decrement-mask) #x2000)
  643. (setf (get 'd1 'pre-decrement-mask) #x4000)
  644. (setf (get 'd0 'pre-decrement-mask) #x8000)
  645.  
  646. (defmacro movem.l (&rest r)
  647.     (incf *assembler-local-address* 2)
  648.     (let ((instruction 0) (mask 0) (ea))
  649.     (if (consp (car r))        ;; post-increment-mode
  650.         (progn
  651.             (setq ea (encode-address (car r)))
  652.             (setq r (cdr r))
  653.             (setq instruction 
  654.                 (+ #x4cc0 
  655.                     (* (encoded-address-mode ea) 8) 
  656.                     (encoded-address-reg ea)))
  657.             (dolist (i r) (setq mask (+ mask (get i 'post-increment-mask))))
  658.             (return (list* instruction mask (encoded-address-data ea)))) 
  659.         (progn                ;; else pre-decrement-mode
  660.             (setq ea (encode-address (car (last r))))
  661.             (setq instruction 
  662.                 (+ #x48c0 
  663.                     (* (encoded-address-mode ea) 8) 
  664.                     (encoded-address-reg ea)))
  665.             (dolist (i r) 
  666.                 (if (symbolp i)
  667.                     (setq mask (+ mask (get i 'pre-decrement-mask)))))
  668.             (return (list* instruction mask (encoded-address-data ea))))))) 
  669.  
  670. (defun long-words (addr) (multiple-value-list (floor addr #x10000)))
  671.  
  672. ;
  673. ;    encode-address
  674. ;    Returns a list consisting of:
  675. ;        (mode reg data1 data2 data3 ...)
  676. ;    where there may be [0..n] data words (16-bit quantities)
  677. ;
  678. (defun encode-address (addr &optional (size 'long) &aux retval) 
  679.     (cond
  680.         ((and (consp addr) (eq (car addr) 'function))
  681.          (let ((exec (exec-address (cadr addr))))
  682.             (add-reference addr)
  683.             (setq retval (list* 7 4 (long-words exec)))))
  684.  
  685.         ((and (consp addr) (eq (car addr) 'quote))
  686.          (let ((exec (address (cadr addr))))
  687.             (add-reference addr)
  688.             (setq retval (list* 7 4 (long-words exec)))))
  689.  
  690.         ((and (consp addr) (eq (car addr) 'symbol-function))
  691.          (let ((func (address (symbol-function (cadr addr)))))
  692.             (add-reference addr)
  693.             (setq retval (list* 7 4 (long-words func)))))
  694.  
  695.         ((symbolp addr)
  696.          (cond
  697.             ((member addr d-registers) 
  698.                 (setq retval (list 0 (symbol-value addr))))
  699.             ((member addr a-registers) 
  700.                 (setq retval (list 1 (symbol-value addr))))
  701.             (t 
  702.                 (add-reference `(symbol-value ,addr))
  703.                 (setq addr (symbol-value addr))
  704.                 (if (eq size 'long)
  705.                     (setq retval (list* 7 4 (long-words addr)))
  706.                     (setq retval (list 7 4 (mod addr #x10000)))))))
  707.  
  708.         ((consp addr)
  709.          (setq retval 
  710.             (cond
  711.                 ((member (car addr) a-registers) 
  712.                  (if (and (cdr addr) (/= (cadr addr) 0))
  713.                      (list* 5 (symbol-value (car addr)) (cdr addr))
  714.                     (list 2 (symbol-value (car addr)))))
  715.                 ((member (car addr) a-inc-registers) 
  716.                  (list 3 (symbol-value (car addr))))
  717.                 ((member (car addr) a-dec-registers) 
  718.                  (list 4 (symbol-value (car addr))))
  719.                 ((and (symbolp (car addr)) (null (cdr addr)))
  720.                  (add-reference `(symbol-value ,(car addr)))
  721.                  (list* 7 1 (long-words (symbol-value (car addr)))))
  722.                 ((and (integerp (car addr)) (null (cdr addr)))
  723.                  (list* 7 1 (long-words (car addr))))
  724.                 (t (error "Unknown address expression: ~A" addr)))))
  725.  
  726.         ((integerp addr)
  727.          (if (eq size 'long)
  728.             (setq retval (list* 7 4 (long-words addr)))
  729.             (setq retval (list 7 4 (mod addr #x10000)))))
  730.             
  731.         (t (error "Unknown address expression: ~A" addr)))
  732.  
  733.     (if (> (length retval) 2)
  734.         (incf *assembler-local-address* (* 2 (length retval))))
  735.     (return retval))
  736.  
  737. ;;
  738. ;;    encoded-address-mode
  739. ;;    Returns the mode (integer) of the passed address structure.
  740. ;;
  741. (defun encoded-address-mode (addr)
  742.     (car addr))
  743.  
  744. (defun encoded-address-reg (addr)
  745.     (cadr addr))
  746.  
  747. (defun encoded-address-data (addr)
  748.     (cddr addr))
  749.     
  750. (defun assemble (assembler-instructions references &optional environment)
  751.   (let*
  752.     ((label-table (make-hash-table :test #'eql))
  753.       (newlist nil)
  754.       (codelist nil)
  755.       (*assembler-address* 0)
  756.       (*assembler-local-address* 0)
  757.       (*assembler-references* nil)
  758.       operator)
  759.  
  760.     (do ((n assembler-instructions (cdr n))
  761.          statement)
  762.         ((null n))
  763.         (setq statement (car n))
  764.         (cond
  765.             ;; if it is a label, add it to the hash table
  766.             ((symbolp statement) 
  767.              (setf (gethash statement label-table) *assembler-address*))
  768.             ((consp statement)
  769.              (if (integerp (car statement))     ;; skip address if there is one
  770.                  (setq statement (cdr statement)))
  771.              
  772.              ;; make sure there is a macro definition
  773.              (setq operator (car statement))
  774.              (unless (symbolp operator) 
  775.                  (error "Invalid instruction: ~A" operator))
  776.              (unless (macro-function operator)
  777.                  (error "No definition for instruction: ~A" statement))
  778.  
  779.              ;; expand the macro one time
  780.              (setq *assembler-local-address* 2)    ;; reset this each instruction
  781.              (setq statement (macroexpand-1 statement))
  782.              
  783.              ;; check for multiple statement result (assembler macro expansion)
  784.              (if (and (consp statement) (not (integerp (car statement))))
  785.                  ;; just splice in the new instructions and continue
  786.                 (setq n (append (list nil) statement (cdr n)))
  787.                 (if (consp statement)
  788.                     ;; This address is only correct because we are requiring
  789.                     ;; all branch destinations to be 16-bit offsets. 
  790.                     ;; This avoids having to calculate the sizes here.
  791.                     ;; i.e. each symbol becomes one 16-bit displacement word.
  792.                     (progn
  793.                         (incf *assembler-address* (* (length statement) 2))
  794.                         (push statement newlist)))))
  795.             
  796.             ;; error if not a symbol or a list
  797.             (t (error "Invalid label encountered: ~A" statement))))
  798.             
  799.     ;; Now go through and append all the sublists together,
  800.     ;; resolving branch addresses as we go.
  801.     ;; We only currently support 16-bit displacements in the branch
  802.     ;; instructions.
  803.  
  804.     (setq newlist (reverse newlist))
  805.     (setq *assembler-address* 0)
  806.     (dolist (statement newlist)
  807.         
  808.         ;; check for branch instructions
  809.         (setq operator (car statement))
  810.         (if (= (truncate operator #x1000) 6)
  811.             (if (and (consp (cdr statement))
  812.                     (symbolp (cadr statement)))
  813.                 (let* ((sym (cadr statement))
  814.                         (value (gethash sym label-table)))
  815.                     (unless value 
  816.                         (error "Label not found: ~A" sym))
  817.                     (unless (integerp value) 
  818.                         (error "Invalid label found.~%~ALabel: ~A Value: ~A" sym value))
  819.                     (setf (cadr statement) (- value (+ *assembler-address* 2))))))
  820.         
  821.         (incf *assembler-address* (* 2 (length statement)))
  822.         (dolist (n statement) (push n codelist)))
  823.         
  824.     (%build-function (reverse codelist) *assembler-references* environment)))
  825.  
  826. (defun add-reference (ref &optional (offset 0))
  827.     (push 
  828.         (cons ref (+ *assembler-address* *assembler-local-address* offset)) 
  829.         *assembler-references*))
  830.  
  831. )  ;; close enclosing eval-when form
  832.     
  833. ;;    add defasm to the common lisp package
  834.  
  835. (eval-when (:compile-toplevel :load-toplevel :execute)
  836.     (in-package :common-lisp)
  837.     (export 'common-lisp::defasm))
  838.  
  839. (eval-when (:compile-toplevel :load-toplevel :execute)
  840. (defmacro defasm (name lambda-list &rest forms)
  841. ;    (declare (unused lambda-list))
  842.     (let ((doc-form nil))
  843.         (if (and (typep (car forms) 'string)
  844.                 (cdr forms))
  845.             (progn
  846.                 (setq doc-form 
  847.                     `((setf (documentation ',name 'function) ,(car forms))))
  848.                 (setq forms (cdr forms))))
  849.  
  850.         `(progn
  851.             ,@doc-form
  852.             (setf (symbol-function ',name) ,(car forms))
  853.             (null-environment (function ,name))
  854.             ',name))) 
  855. ) ;; close eval-when
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.